package com.ebt.m.proposal_v2.record;

import android.Manifest;
import android.os.CountDownTimer;

import com.ebt.m.AppContext;
import com.ebt.m.proposal_v2.utils.PermissionUtils;
import com.ebt.m.commons.utils.Logger;

import java.io.File;
import java.io.IOException;

/**
 * @author archer.qi
 *         Created on 2017/6/14.
 */
public class RecordingWrapperMp3 {
    private static RecordingWrapperMp3 INSTANCE;

    public static RecordingWrapperMp3 getRecorder() {
        if (INSTANCE == null) {
            synchronized (RecordingWrapperMp3.class) {
                if (INSTANCE == null) {
                    INSTANCE = new RecordingWrapperMp3();
                }
            }
        }
        return INSTANCE;
    }

    public static final String TIP_TIME_TOO_SHORT = "说话时间太短";
    public static final String TIP_TIME_TOO_LONG = "说话时间超长";
    public static final String TIP_CANCEL = "录音已取消";
    public static final String TIP_PERMISSION_REFUSED = "录音权限没开启";

    private MP3RecorderApi mRecordingApi;
    private RecordParameter mRecordingParam;

    private RecordingCountDownTimer mRecordingTimer;
    private long mRecordingMillis; // 单位秒
    private VolumeTimer mRecordingVolumeTimer;
    private boolean isRecordingFinish;
    private boolean isRecordingStart;

    private OnRecordingListener mRecordingListener;

    private RecordingWrapperMp3() {
        mRecordingApi = new MP3RecorderApi();
        mRecordingParam = new RecordParameter();
    }

    public void setRecordingListener(OnRecordingListener listener) {
        mRecordingListener = listener;
    }

    public void setRecordingTarget(String dir, String fileName) {
        mRecordingParam.setmRecordingTargetDir(dir);
        mRecordingParam.setmRecordingTargetFileName(fileName);
    }

    public void setRecordingRule(int maxTime, int minTime, int countdown) {
        mRecordingParam.setmMaxRecordingTime(maxTime);
        mRecordingParam.setmMinRecordingTime(minTime);
        mRecordingParam.setmReordingCountDown(countdown);
    }

    public void deleteRecordingTargetFile() {
        File targetFile = new File(mRecordingParam.getmRecordingTargetDir(), mRecordingParam.getmRecordingTargetFileName());
        targetFile.deleteOnExit();
    }

    /**
     * 检查录音权限是否开启
     *
     * @return
     */
    public boolean checkRecordPermission() {
        boolean isPermissionGranted = PermissionUtils.isPermissionStart(AppContext.getInstance().getApplicationContext(), Manifest.permission.RECORD_AUDIO);
        if (!isPermissionGranted) {
            if (mRecordingListener != null) {
                mRecordingListener.onPermissionUndefined();
            }
            return false;
        }
        return true;
    }

    public void startRecording() throws IOException, IllegalStateException {
        if (!checkRecordPermission()) {
            return;
        }

        if (mRecordingTimer != null) {
            mRecordingTimer.cancel();
            mRecordingTimer = null;
        }
        if (mRecordingVolumeTimer != null) {
            mRecordingVolumeTimer.cancel();
            mRecordingVolumeTimer = null;
        }
        mRecordingTimer = new RecordingCountDownTimer(mRecordingParam.getmMaxRecordingTime() * 1000, 1000);
        mRecordingTimer.start();

        mRecordingVolumeTimer = new VolumeTimer(mRecordingParam.getmMaxRecordingTime() * 1000, 50);
        mRecordingVolumeTimer.start();

        try {
            isRecordingStart = true;
            isRecordingFinish = false;
            mRecordingApi.startMP3Recorder(mRecordingParam.getmRecordingTargetDir(), mRecordingParam.getmRecordingTargetFileName());
            if (mRecordingListener != null) {
                mRecordingListener.onRecordingStart();
            }
        } catch (IllegalStateException e) {
            e.printStackTrace();
            // 权限尚未开启
            cancelRecording();
            if (mRecordingListener != null) {
                mRecordingListener.onPermissionUndefined();
            }
        }
    }

    public void stopRecording() {
        if (!isRecordingStart) {
            return;
        }
        if (isRecordingFinish) {
            return;
        }
        if (mRecordingTimer != null) {
            mRecordingTimer.cancel();
            mRecordingTimer = null;
        }
        if (mRecordingVolumeTimer != null) {
            mRecordingVolumeTimer.cancel();
            mRecordingVolumeTimer = null;
        }
        mRecordingApi.stopMP3Recorder();
        handleRecordingFinish();
    }

    public void cancelRecording() {
        if (isRecordingFinish) {
            return;
        }
        if (mRecordingTimer != null) {
            mRecordingTimer.cancel();
            mRecordingTimer = null;
        }
        if (mRecordingVolumeTimer != null) {
            mRecordingVolumeTimer.cancel();
            mRecordingVolumeTimer = null;
        }
        mRecordingApi.stopMP3Recorder();
        deleteRecordingTargetFile();
        isRecordingFinish = true;
        isRecordingStart = false;
        if (mRecordingListener != null) {
            mRecordingListener.onRecordingCancel();
        }
    }

    /**
     * 录音结束处理
     */
    private void handleRecordingFinish() {
        if (mRecordingMillis <= mRecordingParam.getmMinRecordingTime()) {
            if (mRecordingListener != null) {
                mRecordingListener.onRecordingTip(TIP_TIME_TOO_SHORT);
                cancelRecording();
            }
            return;
        }
        isRecordingFinish = true;
        isRecordingStart = false;
        if (mRecordingListener != null) {
            mRecordingListener.onRecordingFinish(mRecordingParam.getmRecordingTargetDir(), mRecordingParam.getmRecordingTargetFileName(), mRecordingMillis);
        }
    }

    private int getCalculatedVolume() {
        int VOL = mRecordingApi.getRealVolume();
        int MAX = mRecordingApi.getMaxVolume() / 10;
        return VOL / MAX;
    }

    public class VolumeTimer extends CountDownTimer {

        /**
         * @param millisInFuture    The number of millis in the future from the call
         *                          to {@link #start()} until the countdown is done and {@link #onFinish()}
         *                          is called.
         * @param countDownInterval The interval along the way to receive
         *                          {@link #onTick(long)} callbacks.
         */
        public VolumeTimer(long millisInFuture, long countDownInterval) {
            super(millisInFuture, countDownInterval);
        }

        @Override
        public void onTick(long millisUntilFinished) {
            if (mRecordingListener != null) {
                int volumeRatio = getCalculatedVolume();
                mRecordingListener.onRecordingVolumeUpdate(volumeRatio);
            }
        }

        @Override
        public void onFinish() {

        }
    }


    public class RecordingCountDownTimer extends CountDownTimer {

        /**
         * @param millisInFuture    The number of millis in the future from the call
         *                          to {@link #start()} until the countdown is done and {@link #onFinish()}
         *                          is called.
         * @param countDownInterval The interval along the way to receive
         *                          {@link #onTick(long)} callbacks.
         */
        public RecordingCountDownTimer(long millisInFuture, long countDownInterval) {
            super(millisInFuture, countDownInterval);
            mRecordingMillis = 0;
        }

        @Override
        public void onTick(long millisUntilFinished) {
            mRecordingMillis = mRecordingParam.getmMaxRecordingTime() - millisUntilFinished / 1000; //120s开始计时
            Logger.i("->录音时间： " + mRecordingMillis);
            if (millisUntilFinished <= mRecordingParam.getmReordingCountDown() * 1000) {
                // 当前计时进入了倒计时范围
                if (mRecordingListener != null) {
                    mRecordingListener.onCountDown((int) (millisUntilFinished / 1000));
                }
            }
        }

        @Override
        public void onFinish() {
            mRecordingMillis = mRecordingParam.getmMaxRecordingTime();
            stopRecording();
        }
    }

    public interface OnRecordingListener {
        /**
         * 倒计时
         *
         * @param countdown
         */
        void onCountDown(int countdown);

        /**
         * 提示： 如录音时间太短
         */
        void onRecordingTip(String msg);

        /**
         * 录音结束
         *
         * @param dir
         * @param fileName
         * @param duration
         */
        void onRecordingFinish(String dir, String fileName, long duration);

        /**
         * 录音开始
         */
        void onRecordingStart();

        /**
         * 录音期间，监听音量大小
         */
        void onRecordingVolumeUpdate(int volume);

        /**
         * 录音取消
         */
        void onRecordingCancel();

        /**
         * 未开启权限
         */
        void onPermissionUndefined();
    }

}
